/*
 * login_mgr.cpp
 *
 *  Created on: 2024年7月9日
 *      Author: Dylan.Gao
 */

#include <dm/session/login_mgr.hpp>

#include <dm/os/sys/host_data_mgr.hpp>
#include <dm/env/cfg.hpp>
#include <dm/os/db/db.hpp>
#include <dm/os/db/resultset.hpp>
#include <dm/scoped_ptr.hpp>
#include <dm/os/log/logger.hpp>
#include <dm/utility/md5.hpp>

namespace dm{
namespace session{

static const char* logModule = "CLoginMgr.session";

/**
 * 登陆信息
 */
struct SLoginInfo{
	CLoginMgr::EAccountType accountType;
	userid_t id;
	dm::uint64 authorities;
	dm::CDateTime loginTime;
};

static bool reader( const SLoginInfo& s,SLoginInfo& d ){
	d.accountType = s.accountType;
	d.id = s.id;
	d.authorities = s.authorities;
	d.loginTime = s.loginTime;

	return true;
}

static bool writer( const SLoginInfo& s,SLoginInfo& d ){
	if( s.id==-1 ){
		// 登出
		if( d.id==-1 ){
			log().info(STATICMODULE "当前未登陆");
			return false;
		}

		d.id = -1;
		return true;
	}else{
		// 登陆
		if( d.id!=-1 ){
			log().info(STATICMODULE "用户已经登陆");
			return false;
		}

		d.accountType = s.accountType;
		d.id = s.id;
		d.authorities = s.authorities;
		d.loginTime = s.loginTime;

		return true;
	}
}

// 本地备份信息
static SLoginInfo LocalLoginInfo;

CLoginMgr::CLoginMgr(){
}

CLoginMgr* CLoginMgr::ins(){
	static CLoginMgr ins;
	return &ins;
}

bool CLoginMgr::login( const char* account,const char* pwd,EAccountType at ){
	dm::env::CCfg& cfg = dm::env::CCfg::ins();
	dm::TScopedPtr<dm::os::CDb> db(dm::os::createDb(cfg.user_dbName().c_str(), cfg.user_dbHost().c_str(), cfg.user_dbEngine().c_str(), cfg.user_dbPort()));

	if( !db ){
		log().warnning(THISMODULE "创建数据库失败");
		return false;
	}

	if( !db->connect(cfg.user_dbUsr().c_str(), cfg.user_dbPwd().c_str()) ){
		log().warnning(THISMODULE "连接数据库失败{%s@$s %s:%d",cfg.user_dbUsr().c_str(),cfg.user_dbName().c_str(),cfg.user_dbHost().c_str(),cfg.user_dbPort());
		return false;
	}

	// 查询用户
	char sql[256];
	dm::utility::CMd5 md5;
	md5.update(pwd, strlen(pwd));

	if( at==AtUser )
		std::sprintf(sql,"SELECT id FROM t_user where f_del not TRUE and f_noLogin not TRUE and account='%s' and pwd='%s'",account,md5.toString().c_str());
	else
		std::sprintf(sql,"SELECT id FROM t_worker where f_del not TRUE and f_noLogin not TRUE and account='%s' and pwd='%s'",account,md5.toString().c_str());

	dm::TScopedPtr<dm::os::CResultSet> rs(db->query(sql));
	if( !rs ){
		log().warnning(THISMODULE "查询用户信息失败:%s",account);
		return false;
	}

	if( !rs->next() ){
		log().warnning(THISMODULE "用户信息校验失败:%s",account);
		return false;
	}

	LocalLoginInfo.id = rs->asInt64(0);
	LocalLoginInfo.accountType = at;
	LocalLoginInfo.loginTime = dm::CTimeStamp::cur();

	return dm::os::CHostDataMgr::ins().write(LocalLoginInfo, writer);
}

bool CLoginMgr::logout(){
	LocalLoginInfo.id = -1;
	return dm::os::CHostDataMgr::ins().write<SLoginInfo>(LocalLoginInfo, writer);
}

bool CLoginMgr::refresh(){
	return dm::os::CHostDataMgr::ins().read<SLoginInfo>(LocalLoginInfo, reader);
}

}
}
